import random
import math

import pygame


class Boid:
    def __init__(self, x, y):
        self.position = [x, y]
        self.velocity = [random.uniform(-1, 1), random.uniform(-1, 1)]
        self.perception_radius = 100

    def separation(self, boids):
        steering = [0, 0]
        count = 0
        for boid in boids:
            distance = math.sqrt(
                (self.position[0] - boid.position[0]) ** 2 + (self.position[1] - boid.position[1]) ** 2)
            if distance < self.perception_radius:
                diff = [self.position[0] - boid.position[0], self.position[1] - boid.position[1]]
                if distance != 0:
                    steering[0] += diff[0] / distance
                    steering[1] += diff[1] / distance
                count += 1
        if count > 0:
            steering[0] /= count
            steering[1] /= count
        return steering

    def alignment(self, boids):
        steering = [0, 0]
        count = 0
        for boid in boids:
            steering[0] += boid.velocity[0]
            steering[1] += boid.velocity[1]
            count += 1
        if count > 0:
            steering[0] /= count
            steering[1] /= count
        return steering

    def cohesion(self, boids):
        steering = [0, 0]
        count = 0
        center_of_mass = [0, 0]
        for boid in boids:
            center_of_mass[0] += boid.position[0]
            center_of_mass[1] += boid.position[1]
            count += 1
        if count > 0:
            center_of_mass[0] /= count
            center_of_mass[1] /= count
            diff = [center_of_mass[0] - self.position[0], center_of_mass[1] - self.position[1]]
            steering[0] += diff[0]
            steering[1] += diff[1]
        return steering

    def update(self, boids):
        sep = self.separation(boids)
        ali = self.alignment(boids)
        coh = self.cohesion(boids)
        self.velocity[0] += sep[0] * 1.5 + ali[0] * 1.5 + coh[0] * 1.5
        self.velocity[1] += sep[1] * 1.5 + ali[1] * 1.5 + coh[1] * 1.5
        self.position[0] += self.velocity[0]
        self.position[1] += self.velocity[1]

    def draw(self, screen):
        pygame.draw.circle(screen, "white", (self.position[0], self.position[1]),10)
